﻿using System;
using System.Collections.Generic;
using System.Text;

namespace X3DLib
{
    namespace WaterScriptFactor
    {
        public class WaterBaseScript : ScriptContent
        {
            /// <summary>
            /// 获取触碰处坐标
            /// </summary>
            /// <returns></returns>
            public string touch_position()
            {
                return "function touch_position(value)\n"
                        + "{\n"

                            + "touch_pos=value;\n"

                        + "}\n";
            }
            /// <summary>
            /// 实体节点的控制脚本
            /// </summary>
            /// <returns></returns>
            public string waterbase()
            {
                return
                   this.contextHead()
                   + "\n"
                   + this.start(""
                                + "grid.xSpacing=xS;\n"
                                + "grid.zSpacing=zS;\n"
                                + "grid.xDimension=xD;\n"
                                + "grid.zDimension=zD;\n"
                                )
                   + "\n"
                   + this.touch_change("touch_is=value;;\n")
                   + "\n"
                   + this.touch_position()
                   + "\n"
                   + this.contextEnd();
            }
            /// <summary>
            /// 初始化grid各个网格的时间
            /// </summary>
            /// <returns>脚本字符串</returns>
            public string init_gridtimearray()
            {
                return "function init_gridtimearray()\n"
                        + "{\n"

                            + "for(i=0;i<zD;i++)\n"
                            + "{\n"
                                + "for(j=0;j<xD;j++)\n"
                                + "{\n"
                                    + "GridTimeArray[i*xD+j]=0;\n"
                                + "}\n"
                            + "}\n"

                        + "}\n";
            }
            /// <summary>
            /// 初始化空闲节点索引
            /// </summary>
            /// <returns></returns>
            public string init_freepartarray()
            {
                return "function init_freepartarray()//remember the free particle to help find out them index\n"
                        + "{\n"

                            + "for(i=1;i<nodeNum;i++)\n"
                            + "{\n"
                                + "FreePartArray[i-1]=i;\n"
                                + "FreeNum=nodeNum-1;\n"
                            + "}\n"

                        + "}\n";

            }
            /// <summary>
            /// 初始化环境
            /// </summary>
            /// <returns></returns>
            public string init_environment()
            {
                return "function init_environment()\n"
                        + "{\n"

                            + "nodes=group.children;	//get nodes including one evironment and num of particles ,also one waterbase and one touch\n"
                            + "nodeNum=nodes.length-2; //get the waterbase index\n"
                            + "color=nodes[0].color;	//get the evironment color setting\n"
                            + "range=nodes[0].range;	//get the range of water\n"
                            + "life=nodes[0].life;	//get particles' life\n"
                            + "gravity=nodes[0].gravity;//get evironment's gravity\n"
                            + "wind=nodes[0].wind;	//get evironment's wind\n"

                        + "}\n";
            }
            /// <summary>
            /// 初始化水体
            /// </summary>
            /// <returns></returns>
            public string init_waterbase()
            {
                return "function init_waterbase()//initialize waterbase\n"
                        + "{\n"

                            + "//setting the waterbase's grid spacing to make water change like the wind do it.(maybe can be based on the wind params)\n"
                            + "//now still not connect it with wind param\n"
                            + "nodes[nodeNum].xS=0.1*Math.random()+0.1;\n"
                            + "nodes[nodeNum].zS=0.1*Math.random()+0.15;\n"
                            + "//setting xD,zD to waterbase's grid\n"
                            + "xD=nodes[nodeNum].xD=Math.round( range[0]/nodes[nodeNum].xS );\n"
                            + "zD=nodes[nodeNum].zD=Math.round( range[2]/nodes[nodeNum].zS );\n"
                            + "//init_gridtimearry()\n"
                            + "init_gridtimearray();\n"
                            + "//set base position and the base center is (0 0 0)\n"
                            + "nodes[nodeNum].position[0]=-1*0.5*range[0];\n"
                            + "nodes[nodeNum].position[1]=0;\n"
                            + "nodes[nodeNum].position[2]=-1*0.5*range[2];\n"
                            + "\n"
                            + "nodes[nodeNum].emissiveColor[0]=color[0];\n"
                            + "nodes[nodeNum].emissiveColor[1]=color[1];\n"
                            + "nodes[nodeNum].emissiveColor[2]=color[2];\n"
                            + "for(i=0;i<zD;i++)\n"
                            + "{\n"
                                + "for(j=0;j<xD;j++)\n"
                                + "{\n"
                                    + "index=i*xD+j;\n"
                                    + "x=j*nodes[nodeNum].xS + (-1*0.5*range[0]);\n"
                                    + "z=i*nodes[nodeNum].zS + (-1*0.5*range[2]);\n"
                                    + "if( i==0 || j==0 || i==zD-1 || j==xD-1 )\n"
                                    + "{\n"
                                        + "nodes[nodeNum].height[index]=Math.random()*0.01;\n"
                                    + "}\n"
                                    + "else\n"
                                    + "{\n"
                                        + "if(Math.random()>0.99)\n"
                                        + "{\n"
                                            + "\n"
                                            + "nodes[nodeNum].height[index]=Math.random()*0.2;\n"
                                            + "if(Math.random()>0.5)\n"
                                                + "water_wave(x,nodes[nodeNum].height[index],z);\n"
                                        + "}\n"
                                    + "}\n"
                                + "}\n"
                            + "}\n"

                        + "}\n";
            }
            /// <summary>
            /// 实时更新变化水体
            /// </summary>
            /// <returns></returns>
            public string update_waterbase()
            {
                return "function update_waterbase()\n"
                        + "{\n"
                            + "counter=0;\n"
                            + "heightest=0.0;\n"
                            + "//init_waterbase();\n"
                            + "nodes[nodeNum].transparency=0.05*Math.random()+0.9;\n"
                            + "\n"
                            + "for(i=0;i<zD;i++)//random to begin\n"
                            + "{\n"
                                + "for(j=0;j<xD;j++)\n"
                                + "{\n"
                                    + "index=i*xD+j;\n"
                                    + "x=(j)*nodes[nodeNum].xS + (-1*0.5*range[0]);\n"
                                    + "z=(i)*nodes[nodeNum].zS + (-1*0.5*range[2]);\n"
                                    + "if( nodes[nodeNum].height[index]>0 )//height wave\n"
                                    + "{\n"
                                        + "GridTimeArray[index]++;\n"
                                        + "//wind[0],wind[2]\n"
                                        + "if(Math.random()>0.998)\n"
                                        + "{\n"
                                            + "add=0;\n"
                                            + "if( j<xD-1 && (wind[0]>wind[2]) )\n"
                                                + "add=1;\n"
                                            + "if( i<zD-1 && (wind[2]>wind[0]) )\n"
                                                + "add=xD;\n"
                                            + "\n"
                                            + "index+=add;\n"
                                            + "GridTimeArray[index]=GridTimeArray[index-add];\n"
                                            + "GridTimeArray[index-add]=0;\n"
                                            + "nodes[nodeNum].height[index]+=nodes[nodeNum].height[index-add];\n"
                                            + "nodes[nodeNum].height[index-add]=0;\n"

                                            + "nodes[nodeNum].height[index]-=0.5*gravity[1]*Math.pow(GridTimeArray[index]*0.02,2);\n"
                                        + "}\n"
                                        + "else\n"
                                        + "{\n"
                                            + "nodes[nodeNum].height[index]-=0.5*gravity[1]*Math.pow(GridTimeArray[index]*0.02,2);\n"
                                        + "}\n"
                                        + "\n"
                                    + "}\n"
                                    + "else\n"
                                    + "{\n"
                                        + "GridTimeArray[index]=0;\n"
                                        + "if(Math.random()>0.99)//reset 1% of points\n"
                                        + "{\n"
                                            + "nodes[nodeNum].height[index]=Math.random()*0.2;\n"
                                            + "if(Math.random()>0.5)\n"
                                                + "water_wave(x,nodes[nodeNum].height[index],z);\n"
                                        + "}\n"
                                    + "}\n"
                                + "}\n"
                            + "}\n"
                            + "Browser.setDescription(xD*zD);\n"
                        + "}\n";
            }
            /// <summary>
            /// 实时根据水体变化水泡
            /// </summary>
            /// <returns></returns>
            public string update_particles()
            {
                return "function update_particles()\n"
                        + "{\n"
                            + "for(i=1;i<nodeNum;i++)\n"
                            + "{\n"
                                + "if(nodes[i].transparency==1)continue;\n"
                                + "nodes[i].age++;\n"
                                + "nodes[i].transparency+=0.01;\n"
                                + "//(v(t+1)+0.5*g*(t+1)^2) - (vt+0.5*g*t^2)=v+0.5*g*(2*t+1)=v+g*t+0.5  //t+1->t+0.02\n"
                                + "nodes[i].position[0]+=( (nodes[i].velocity[0]-wind[0])+(nodes[0].gravity[0]*0.02)*nodes[i].age+0.5 )*0.02;\n"
                                + "nodes[i].position[1]+=( (nodes[i].velocity[1]-wind[1])-(nodes[0].gravity[1]*0.02)*nodes[i].age+0.5 )*0.02;\n"
                                + "nodes[i].position[2]+=( (nodes[i].velocity[2]-wind[2])+(nodes[0].gravity[2]*0.02)*nodes[i].age+0.5 )*0.02;\n"
                                + "if(nodes[i].position[1]<0.1||nodes[i].age>30)\n"
                                + "{\n"
                                + "//release particle and add it into freeparticles\n"
                                + "FreeNum++;\n"
                                + "FreePartArray[FreeNum-1]=i;\n"
                                + "nodes[i].transparency=1;\n"
                                + "}\n"
                            + "}\n"
                        + "}\n";
            }
            /// <summary>
            /// 水浪 生成一个浪花
            /// </summary>
            /// <returns></returns>
            public string water_wave()
            {
                return "function water_wave(x,y,z)//wave position\n"
                        + "{\n"
                            + "num=Math.round(Math.random()*20+20);\n"
                            + "temp=(FreeNum>=num?num:FreeNum);\n"
                            + "count=0;\n"
                            + "index=0;\n"
                            + "while( count< temp )\n"
                            + "{\n"
                                + "index=FreePartArray[FreeNum-1];\n"
                                + "//set size\n"
                                + "nodes[index].size[0]=nodes[index].size[1]=nodes[index].size[2]=nodes[0].size*Math.random();\n"
                                + "//set position\n"
                                + "nodes[index].position[0]=x;\n"
                                + "nodes[index].position[1]=y/2;\n"
                                + "nodes[index].position[2]=z;\n"
                                + "//set speed\n"
                                + "nodes[index].velocity[0]=(Math.random()-0.5)*4;\n"
                                + "nodes[index].velocity[1]=Math.random()*2;\n"
                                + "nodes[index].velocity[2]=(Math.random()-0.5)*4;\n"
                                + "//set transparency\n"
                                + "nodes[index].transparency=Math.random()*0.1+0.4;\n"
                                + "//set age\n"
                                + "nodes[index].age=0;\n"
                                + "//set color\n"
                                + "nodes[index].emissiveColor[0]=nodes[index].emissiveColor[1]=nodes[index].emissiveColor[2]=Math.random()*0.3+0.7;\n"
                                + "count++;\n"
                                + "FreeNum--;\n"
                            + "}\n"
                            + "//Browser.setDescription(index);\n"
                        + "}\n";
            }
            /// <summary>
            /// 当鼠标触碰水体时响应
            /// </summary>
            /// <returns></returns>
            public string on_base_touch()
            {
                return "function on_base_touch()//when the base of water being touched call this function\n"
                        + "{\n"
                            + "//change touch_pos into index of height\n"
                            + "i=Math.round(nodes[nodeNum].touch_pos[2]/nodes[nodeNum].zS);	//z\n"
                            + "j=Math.round(nodes[nodeNum].touch_pos[0]/nodes[nodeNum].xS);	//x\n"
                            + "nodes[nodeNum].height[i*xD+j]=Math.random();\n"
                            + "water_wave(nodes[nodeNum].touch_pos[0]+ (-1*0.5*range[0]),nodes[nodeNum].height[i*xD+j],nodes[nodeNum].touch_pos[2]+ (-1*0.5*range[2]));\n"
                        + "}\n";
            }
            /// <summary>
            /// 水平面粒子系统脚本字符串生成
            /// </summary>
            /// <returns></returns>
            public string waterWithBaseMain()
            {
                return
                   this.contextHead()
                   + "\n"
                   + this.initialize(""
                                    + "init_environment();\n"
                                    + "init_waterbase();\n"
                                    + "init_particles();\n"
                                    )
                   + this.init_gridtimearray()
                   + "\n"
                   + this.init_freepartarray()
                   + "\n"
                   + this.init_environment()
                   + "\n"
                   + this.init_particles(
                                        "init_freepartarray();\n"
                                        + "for(i=1;i<nodeNum;i++)\n"
                                        + "{\n"
                                            + "nodes[i].transparency=1;//make all particle disappearanced\n"
                                        + "}\n"
                                        )
                   + "\n"
                   + this.init_waterbase()
                   + "\n"
                   + this.update_waterbase()
                   + "\n"
                   + this.update_particles()
                   + "\n"
                   + this.water_wave()
                   + "\n"
                   + this.on_base_touch()
                   + "\n"
                   + this.update(""
                                    + "update_waterbase();\n"
                                    + "update_particles();\n"
                                    )
                   + "\n"
                   + this.start(""
                                   + "update();\n"
                                   + "if(nodes[nodeNum].touch_is)\n"
                                   + "{\n"
                                    + "on_base_touch();\n"
                                   + "}\n"
                                   )
                   + this.touch_change(""
                                         + "color[0]=Math.random();\n"
                                         + "color[1]=Math.random();\n"
                                         + "color[2]=math.random();\n"
                                         )
                   + this.contextEnd();
            }

        }
    }
}
